<?php

namespace yak\layui\helper;

use Yii;
use yii\helpers\ArrayHelper;
use yii\rbac\Role;

/**
 * Class RbacHelper
 * @package yak\helpers
 */
class RbacHelper
{
    public static function permissions()
    {
        $permissions = Yii::$app->authManager->getPermissions();
        return ArrayHelper::map($permissions, 'name', 'description');
    }

    public static function roles()
    {
        $permissions = Yii::$app->authManager->getRoles();
        return ArrayHelper::map($permissions, 'name', 'description');
    }

    /**
     * @param $name
     * @return null|\yii\rbac\Role
     * 获取角色
     */
    public static function getRole($name)
    {
        return Yii::$app->authManager->getRole($name);
    }

    /**
     * @param $name
     * @return null|\yii\rbac\Permission
     * 获取权限节点
     */
    public static function getPermission($name)
    {
        return Yii::$app->authManager->getPermission($name);
    }

    /**
     * @param Role $role
     * @param array $permissions
     * @param array $roles
     * @throws \yii\base\Exception
     */
    public static function setChildrenToRole(Role $role, $permissions = [], $roles = [])
    {
        self::removeChildren($role);
        self::setPermissionChildren($role, $permissions);
        self::setRoleChildren($role, $roles);
    }

    /**
     * @param Role $role
     * @param array $children
     * @throws \yii\base\Exception
     */
    public static function setRoleChildren(Role $role, $children = [])
    {
        foreach ($children as $child) {
            Yii::$app->authManager->addChild($role, self::getRole($child));
        }
    }

    /**
     * @param Role $role
     * @param array $children
     * @throws \yii\base\Exception
     */
    public static function setPermissionChildren(Role $role, $children = [])
    {
        foreach ($children as $child) {
            Yii::$app->authManager->addChild($role, self::getPermission($child));
        }
    }

    /**
     * @param Role $role
     * @return bool
     * 清除角色下所有权限节点、包括子角色
     */
    public static function removeChildren(Role $role)
    {
        return Yii::$app->authManager->removeChildren($role);
    }

    public static function revokeAll($userID)
    {
        \Yii::$app->authManager->revokeAll($userID);
    }

    /**
     * @param $userId
     * @param array $permission
     * @param array $roles
     */
    public static function assign($userId, $permission = [], $roles = [])
    {
        self::revokeAll($userId);
        self::assignPermissionChildren($userId, $permission);
        self::assignRoleChildren($userId, $roles);
    }

    public static function assignRoleChildren($userId, $children = [])
    {
        foreach ($children as $child) {
            Yii::$app->authManager->assign(self::getRole($child), $userId);
        }
    }

    public static function assignPermissionChildren($userId, $children = [])
    {
        foreach ($children as $child) {
            Yii::$app->authManager->assign(self::getPermission($child), $userId);
        }
    }

    public static function rolesChild($role = '')
    {
        return array_keys(Yii::$app->authManager->getChildRoles($role));
    }

    public static function permissionsByRole($role = '')
    {
        return array_keys(Yii::$app->authManager->getPermissionsByRole($role));
    }

    public static function rolesByUser($userID)
    {
        return array_keys(\Yii::$app->authManager->getRolesByUser($userID));
    }

    public static function permissionsByUser($userID)
    {
        return array_keys(\Yii::$app->authManager->getPermissionsByUser($userID));
    }

    public static function autoPermissions($dirname = '', $module = '', $exceptCtrl = [])
    {
        $actions = [];

        // Simple way to get all files in a directory
        $files = new \FilesystemIterator($dirname);

        foreach ($files as $file) {
            $controller = $file->getFilename();
            $match = [];
            preg_match("/([a-zA-Z0-9]+)Controller\.php/", $controller, $match);
            $class = lcfirst($match[1]);

            if (in_array($class, $exceptCtrl)) {
                continue;
            }

            $class = preg_replace_callback('/[A-Z]/', function ($mclass) {
                return '-' . strtolower($mclass[0]);
            }, $class);

            $namespace = empty($module) ? $class : $module . '/' . $class;

            array_push($actions, $namespace . '/*');

            $document = new \SplFileObject($file->getPathname());

            foreach ($document as $line) {

                if (preg_match('/public function action([a-zA-Z0-9_]+)/', $line, $_action)) {
                    if (preg_match('/[A-Z]/', $_action[1])) {
                        $str = lcfirst($_action[1]);
                        $actions[] = $namespace . '/' . preg_replace_callback('/[A-Z]/', function ($matches) {
                                return '-' . strtolower($matches[0]);
                            }, $str);
                    }
                }

            }
        }

        $auth = \Yii::$app->authManager;

        //$auth->removeAllPermissions();

        foreach ($actions as $action) {
            $obj = $auth->createPermission($action);
            $obj->description = $action;
            if (!$auth->getPermission($action)) {
                $auth->add($obj);
            } else {
                $auth->update($action, $obj);
            }
        }

    }
}